package io.renren.com.qywt.controller;

import com.xxl.job.core.biz.model.ReturnT;
import io.renren.com.qywt.dto.AftersaleFinanceCollectDTO;
import io.renren.com.qywt.entity.*;
import io.renren.com.qywt.excel.AftersaleFinanceCollectExcel;
import io.renren.com.qywt.service.*;
import io.renren.commons.log.annotation.LogOperation;
import io.renren.commons.security.user.SecurityUser;
import io.renren.commons.security.user.UserDetail;
import io.renren.commons.tools.constant.Constant;
import io.renren.commons.tools.page.PageData;
import io.renren.commons.tools.utils.Result;
import io.renren.commons.tools.utils.ExcelUtils;
import io.renren.commons.tools.validator.AssertUtils;
import io.renren.commons.tools.validator.ValidatorUtils;
import io.renren.commons.tools.validator.group.AddGroup;
import io.renren.commons.tools.validator.group.DefaultGroup;
import io.renren.commons.tools.validator.group.UpdateGroup;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;


/**
* 财务结算汇总表
*
* @author jiaohj 15110414840@139.com
* @since 3.0 2022-08-10
*/
@RestController
@RequestMapping("finance")
@Api(tags="财务结算汇总表")
public class AftersaleFinanceCollectController {
    @Autowired
    private AftersaleFinanceCollectService aftersaleFinanceCollectService;
    @Autowired
    private TaskStorageFeeService taskStorageFeeService;
    @Autowired
    private TaskReturnFeeService taskReturnFeeService;
    @Autowired
    private TaskPurchaseReturnFeeService taskPurchaseReturnFeeService;
    @Autowired
    private TaskLocationFeeService taskLocationFeeService;
    @Autowired
    private TaskEjectFeeService taskEjectFeeService;
    @Autowired
    private TaskCarriageFeeService taskCarriageFeeService;

    @Autowired
    private AftersaleStorageFeeService storageFeeService;
    @Autowired
    private AftersaleReturnFeeService returnFeeService;
    @Autowired
    private AftersalePurchasereturnFeeService purchaseReturnFeeService;
    @Autowired
    private AftersaleLocationFeeService locationFeeService;
    @Autowired
    private AftersaleEjectFeeService ejectFeeService;
    @Autowired
    private AftersaleCarriageFeeService carriageFeeService;

    public static volatile List<AftersaleStorageFeeEntity> storageFeeList=new ArrayList<>();
    public static volatile List<AftersaleReturnFeeEntity> returnFeeList=new ArrayList<>();
    public static volatile List<AftersalePurchasereturnFeeEntity> purchaseReturnFeeList=new ArrayList<>();
    public static volatile List<AftersaleLocationFeeEntity> locationFeeList=new ArrayList<>();
    public static volatile List<AftersaleEjectFeeEntity> ejectFeeList=new ArrayList<>();
    public static volatile List<AftersaleCarriageFeeEntity> carriageFeeList=new ArrayList<>();

    @GetMapping("page")
    @ApiOperation("分页")
    @ApiImplicitParams({
        @ApiImplicitParam(name = Constant.PAGE, value = "当前页码，从1开始", paramType = "query", required = true, dataType="int") ,
        @ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
        @ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
        @ApiImplicitParam(name = Constant.ORDER, value = "排序方式，可选值(asc、desc)", paramType = "query", dataType="String")
    })
    @PreAuthorize("hasAuthority('aftersale:finance:page')")
    public Result<PageData<AftersaleFinanceCollectDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
        PageData<AftersaleFinanceCollectDTO> page = aftersaleFinanceCollectService.page(params);

        return new Result<PageData<AftersaleFinanceCollectDTO>>().ok(page);
    }

    @GetMapping("{id}")
    @ApiOperation("信息")
    @PreAuthorize("hasAuthority('aftersale:finance:info')")
    public Result<AftersaleFinanceCollectDTO> get(@PathVariable("id") Long id){
        AftersaleFinanceCollectDTO data = aftersaleFinanceCollectService.get(id);

        return new Result<AftersaleFinanceCollectDTO>().ok(data);
    }

    @GetMapping("collect")
    @ApiOperation("汇总")
    @LogOperation("汇总")
    @PreAuthorize("hasAuthority('aftersale:finance:execute')")
    public ReturnT<String> collect(@ApiIgnore @RequestParam String batchNo){
        UserDetail userDetail=SecurityUser.getUser();
        CountDownLatch countDownLatch = new CountDownLatch(6);
        aftersaleFinanceCollectService.deleteFeeByBatchNo(batchNo,userDetail);
        AftersaleFinanceCollectDTO dto=aftersaleFinanceCollectService.getByBatchNo(batchNo);

        new Thread(()->{
            storageFeeList=taskStorageFeeService.getReceiptDetail(userDetail,dto);
            storageFeeService.insertBatch(storageFeeList);
            countDownLatch.countDown();
        }).start();

        new Thread(()->{
            returnFeeList=taskReturnFeeService.getReturnInfoList(userDetail,dto);
            returnFeeService.insertBatch(returnFeeList);
            countDownLatch.countDown();
        }).start();

        new Thread(()->{
            purchaseReturnFeeList=taskPurchaseReturnFeeService.getPurchaseReturnInfoList(userDetail,dto);
            purchaseReturnFeeService.insertBatch(purchaseReturnFeeList);
            countDownLatch.countDown();
        }).start();

        new Thread(()->{
            locationFeeList=taskLocationFeeService.getInventoryInfoList(userDetail,dto);
            locationFeeService.insertBatch(locationFeeList);
            countDownLatch.countDown();
        }).start();

        new Thread(()->{
            ejectFeeList=taskEjectFeeService.getShipmentInfoList(userDetail,dto);
            ejectFeeService.insertBatch(ejectFeeList);
            countDownLatch.countDown();
        }).start();

        new Thread(()->{
            carriageFeeList=taskCarriageFeeService.getCarriageInfoList(userDetail,dto);
            carriageFeeService.insertBatch(carriageFeeList);
            countDownLatch.countDown();
        }).start();

        try {
            countDownLatch.await();
        }catch (InterruptedException ex){
            ex.printStackTrace();
        }

        if(countDownLatch.getCount()==0){
            AftersaleFinanceCollectDTO collectDTO=aftersaleFinanceCollectService.getByBatchNo(batchNo);
            Optional<BigDecimal> storageFee=storageFeeList.stream().map(AftersaleStorageFeeEntity::getProdFee).reduce(BigDecimal::add);
            Optional<BigDecimal> returnFee=returnFeeList.stream().map(AftersaleReturnFeeEntity::getReturnFee).reduce(BigDecimal::add);
            Optional<BigDecimal> purchaseReturnFee=purchaseReturnFeeList.stream().map(AftersalePurchasereturnFeeEntity::getReturnFee).reduce(BigDecimal::add);
            Optional<BigDecimal> locationFee=locationFeeList.stream().map(AftersaleLocationFeeEntity::getLocationFee).reduce(BigDecimal::add);
            Optional<BigDecimal> ejectFee=ejectFeeList.stream().map(AftersaleEjectFeeEntity::getEjectFee).reduce(BigDecimal::add);
            Optional<BigDecimal> carriageFee=carriageFeeList.stream().map(AftersaleCarriageFeeEntity::getCarriageFee).reduce(BigDecimal::add);

            collectDTO.setStorageFee(storageFee.isPresent()?storageFee.get():BigDecimal.ZERO);
            collectDTO.setReturnFee(returnFee.isPresent()?returnFee.get():BigDecimal.ZERO);
            collectDTO.setPurchaseReturnFee(purchaseReturnFee.isPresent()?purchaseReturnFee.get():BigDecimal.ZERO);
            collectDTO.setLocationFee(locationFee.isPresent()?locationFee.get():BigDecimal.ZERO);
            collectDTO.setEjectFee(ejectFee.isPresent()?ejectFee.get():BigDecimal.ZERO);
            collectDTO.setCarriageFee(carriageFee.isPresent()?carriageFee.get():BigDecimal.ZERO);
            aftersaleFinanceCollectService.update(collectDTO);

            storageFeeList.clear();
            returnFeeList.clear();
            purchaseReturnFeeList.clear();
            locationFeeList.clear();
            ejectFeeList.clear();
            carriageFeeList.clear();

            return ReturnT.SUCCESS;
        }
        return ReturnT.FAIL;
    }


    @PostMapping
    @ApiOperation("保存")
    @LogOperation("保存")
    @PreAuthorize("hasAuthority('aftersale:finance:save')")
    public Result save(@RequestBody AftersaleFinanceCollectDTO dto){
        //效验数据
        ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);

        aftersaleFinanceCollectService.save(dto);

        return new Result();
    }

    @PutMapping
    @ApiOperation("修改")
    @LogOperation("修改")
    @PreAuthorize("hasAuthority('aftersale:finance:update')")
    public Result update(@RequestBody AftersaleFinanceCollectDTO dto){
        //效验数据
        ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);

        aftersaleFinanceCollectService.update(dto);

        return new Result();
    }

    @DeleteMapping
    @ApiOperation("删除")
    @LogOperation("删除")
    @PreAuthorize("hasAuthority('aftersale:finance:delete')")
    public Result delete(@RequestBody Long[] ids){
        //效验数据
        AssertUtils.isArrayEmpty(ids, "id");

        aftersaleFinanceCollectService.delete(ids);

        return new Result();
    }

    @GetMapping("export")
    @ApiOperation("导出")
    @LogOperation("导出")
    @PreAuthorize("hasAuthority('aftersale:finance:export')")
    public void export(@ApiIgnore @RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
        List<AftersaleFinanceCollectDTO> list = aftersaleFinanceCollectService.list(params);

        ExcelUtils.exportExcelToTarget(response, null, "财务结算汇总表", list, AftersaleFinanceCollectExcel.class);
    }

}